package org.byqh.dqeai.controller;

import com.easy.query.api.proxy.entity.select.EntityQueryable;
import com.easy.query.core.basic.api.select.Query;
import com.easy.query.core.proxy.AbstractProxyEntity;
import com.easy.query.core.proxy.ProxyEntityAvailable;
import org.byqh.dqeai.common.EasyQueryController;
import org.byqh.dqeai.common.Json;
import org.byqh.dqeai.dto.common.IPage;
import org.byqh.dqeai.dto.common.SysPageDTO;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Function;

public class BaseController<
        TEntity extends ProxyEntityAvailable<TEntity, TProxy>,
        TProxy extends AbstractProxyEntity<TProxy, TEntity>
        > extends EasyQueryController<TEntity, TProxy> {

    /**
     * 查询一条记录
     */
    @GetMapping(value = "/{id}")
    public Json<TEntity> get(@PathVariable String id) {
        return this.getById(id);
    }

    /**
     * 删除一条记录
     */
    @DeleteMapping(value = "/{id}")
    public Json<Boolean> delete(@PathVariable String id) {
        return this.removeById(id);
    }

    /**
     * 根据主键删除。
     *
     * @param id 主键
     * @return {@code true} 删除成功，{@code false} 删除失败
     */
    @DeleteMapping("remove/{id}")
    public Json<Boolean> remove(@PathVariable String id) {
        return this.removeById(id);
    }

    /**
     * 修改一条记录
     */
    @PutMapping(value = "/")
    public Json<Boolean> put(@RequestBody TEntity dto) {
        updateDate(dto);

        return this.update(dto);
    }

    /**
     * 增加一条记录
     */
    @PostMapping(value = "/")
    public Json<Boolean> post(@RequestBody TEntity dto) {
        updateDate(dto);

        return this.save(dto);
    }

    private void updateDate(TEntity obj) {
        // 获取对象的类
        Class<?> clazz = getGenericClass();

        // 遍历类中的所有字段
        for (Field field : clazz.getDeclaredFields()) {
            // 判断字段类型是否为 LocalDateTime
            if (field.getType() == LocalDateTime.class) {
                try {
                    // 设置字段可访问（即使是 private 字段）
                    field.setAccessible(true);

                    // 获取字段的值
                    Object value = field.get(obj);

                    // 如果字段值为 null，则设置为当前时间
                    if (value == null) {
                        field.set(obj, LocalDateTime.now());
                    }
                } catch (IllegalAccessException e) {

                }
            }
        }
    }

    protected <TEntityResult extends TEntity> Json<List<TEntityResult>> listImpl(
            Class<TEntityResult> clazzResult,
            Function<EntityQueryable<TProxy, TEntity>, EntityQueryable<TProxy, TEntity>> listWhere
    ) {
        var query = this.getEntityQueryable();

        if (listWhere != null) {
            query = listWhere.apply(query);
        }

        return Json.success(query.selectAutoInclude(clazzResult).toList());
    }

    protected <TEntityResult extends TEntity> Json<IPage<TEntityResult>> listPageImpl(
            Class<TEntityResult> clazzResult,
            Integer page, Integer size,
            Function<EntityQueryable<TProxy, TEntity>, EntityQueryable<TProxy, TEntity>> listWhere
    ) {
        var query = this.getEntityQueryable();

        if (listWhere != null) {
            query = listWhere.apply(query);
        }

        var pageDto = new SysPageDTO();
        pageDto.setPage(page);
        pageDto.setSize(size);

        return getPageResult(query.selectAutoInclude(clazzResult), pageDto);
    }

    protected <TEntityDto extends TEntity> Json<IPage<TEntityDto>> getPageResult(Query<TEntityDto> query, SysPageDTO pageDto) {
        long current = 1;
        long size = Long.MAX_VALUE;

        if (pageDto != null) {
            current = pageDto.getPage();
            size = pageDto.getSize();
        }

        return Json.success(new IPage<>(current, size, query.toPageResult(current, size)));
    }

    protected Json<IPage<TEntity>> getPageResult(EntityQueryable<TProxy, TEntity> query, SysPageDTO pageDto) {
        long current = 1;
        long size = Long.MAX_VALUE;

        if (pageDto != null) {
            current = pageDto.getPage();
            size = pageDto.getSize();
        }

        return Json.success(new IPage<>(current, size, query.toPageResult(current, size)));
    }
}
